﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Slb.Ocean.Geometry;
using Slb.Ocean.Petrel.DomainObject.Well;
using Slb.Ocean.Petrel.DomainObject;
using Public.Ocean.Petrel.Extensions.Internal;

namespace Public.Ocean.Petrel.Extensions.DomainObject
{
    public static class BoreholeExtensions
    {
        /// <summary>
        /// Calculates the Borehole bottom location for a given domain.
        /// </summary>
        /// <param name="borehole">The borehole.</param>
        /// <param name="output">The output domain.</param>
        /// <returns></returns>
        public static Point3 GetBottomLocation(this Borehole borehole, Domain output)
        {
            return borehole.Transform3(Domain.MD, borehole.Trajectory.Records.Max(r => r.MD), output);
        }

        /// <summary>
        /// Returns all the sub BoreholeCollections.
        /// </summary>
        /// <param name="root">The root.</param>
        /// <returns></returns>
        public static IEnumerable<BoreholeCollection> BoreholeCollectionsRecursive(this BoreholeCollection root)
        {
            return Enumerations.Flatten(new[] { root }, c => c.BoreholeCollections);
        }

        /// <summary>
        /// Traverses the Wells folder and returns all the Boreholes.
        /// </summary>
        /// <param name="collections">The collection.</param>
        /// <param name="predicate">Match predicate for the individual boreholes.</param>
        /// <returns></returns>
        public static IEnumerable<Borehole> GetBoreholesRecursive(this IEnumerable<BoreholeCollection> collections, Func<Borehole, bool> predicate)
        {
            if (predicate == null) throw new ArgumentNullException("predicate");

            foreach (var collection in Enumerations.Flatten(collections, c => c.BoreholeCollections))
            {
                foreach (var borehole in collection)
                {
                    if (predicate(borehole))
                    {
                        yield return borehole;
                    }
                }
            }
        }

        /// <summary>
        /// Traverses the Wells folder and returns all the Boreholes.
        /// </summary>
        /// <param name="collections">The collections.</param>
        /// <returns></returns>
        public static IEnumerable<Borehole> GetBoreholesRecursive(this IEnumerable<BoreholeCollection> collections)
        {
            return GetBoreholesRecursive(collections, borehole => true);
        }

        /// <summary>
        /// Traverses the Wells folder and returns all the Boreholes.
        /// </summary>
        /// <param name="collection">The collection.</param>
        /// <param name="predicate">Match predicate for the individual boreholes.</param>
        /// <returns></returns>
        public static IEnumerable<Borehole> GetBoreholesRecursive(this BoreholeCollection collection, Func<Borehole, bool> predicate)
        {
            return GetBoreholesRecursive(new[] { collection }, predicate);
        }

        /// <summary>
        /// Traverses the Wells folder and returns all the Boreholes.
        /// </summary>
        /// <param name="collection">The collection.</param>
        /// <returns></returns>
        public static IEnumerable<Borehole> GetBoreholesRecursive(this BoreholeCollection collection)
        {
            return GetBoreholesRecursive(new[] { collection }, borehole => true);
        }
    }
}
